<?php
namespace api\modules\v1\models\friend;

use api\modules\v1\models\imUser\ImUser;
use api\modules\v1\models\imUser\ImUserLevel;
use api\modules\v1\models\user\User;
use common\models\CacheKeys;
use common\models\Functions;
use common\models\im\Im;
use common\models\Status;
use common\models\user\UserUnusualLog;
use Yii;
use yii\base\Exception;
use yii\helpers\ArrayHelper;

class FriendApply extends \common\models\friend\FriendApply
{

    /**
     * 申请好友
     * @return array
     */
    public function apply() {
        $trans = static::getDb()->beginTransaction();

        try {
            $userModel = new User();
            $redis = Yii::$app->redis;
            $user = $userModel -> checkUser();
            CacheKeys::checkFrequency("APPLY_FRIEND_".$user['id'],1);

            $code = Yii::$app->request->post('code','');
            $message = Yii::$app->request->post('message','');
            $type = Yii::$app->request->post('type',Status::IM_ADD_FRIEND_TYPE_NORMAL);
            if (!$code) {
                throw new Exception('未知用户信息！');
            }

            if (!in_array($type,array_keys(Status::IM_ADD_FRIEND_TYPE_MAP))) {
                throw new Exception('未知添加好友方式！');
            }

            $where['tx_code'] = $code;
            $searchUser = $userModel::getObjectOneByWhere($where,'id,tx_code,login_name,user_code')->with()->asArray()->one();
            if (empty($searchUser)) {
                throw new Exception('未知用户信息！');
            }

            if ($type == Status::IM_ADD_FRIEND_TYPE_BUSINESS_CARD && $searchUser['is_add_friend_by_business_card'] == Status::COMMON_RADIO_NO) {
                throw new Exception('不可申请添加好友！');
            }

            if ($type == Status::IM_ADD_FRIEND_TYPE_QR_CODE && $searchUser['is_add_friend_by_qr_code'] == Status::COMMON_RADIO_NO) {
                throw new Exception('不可申请添加好友！');
            }

            // 判断是否为黑名单 A -> B
            $blackAtoB = (new Im())->checkBlack($user['tx_code'],$searchUser['tx_code']);
            if ($blackAtoB){
                if ($blackAtoB == "BlackCheckResult_Type_AWithB"){
                    throw new Exception("你已把该用户拉黑，无法申请添加好友，请先移除黑名单");
                }
            }

            // 判断是否为黑名单 B -> A
            $blackBtoA = (new Im())->checkBlack($searchUser['tx_code'],$user['tx_code']);
            if ($blackBtoA){
                if ($blackBtoA == "BlackCheckResult_Type_AWithB"){
                    throw new Exception("该用户已把你拉黑，无法申请添加好友");
                }
            }

            $applyTime = $redis->get('IM_APPLY_FRIEND_TIME_'. $user['id']);
            if ($applyTime) {
                // 判断是否一分钟内的缓存
                $time = time();
                if ($time - $applyTime < 60) {
                    // 判断是否申请超过十次
                    $applyCount = $redis->get('IM_APPLY_FRIEND_COUNT_'. $user['id']);
                    if( $applyCount > 10){
                        // 禁言
                        UserUnusualLog::disableUser($user['id'], Status::USER_UNUSUAL_TYPE_CHAT, 1, '一分钟内向陌生人发送加好友申请十次的，自动作禁言处理');

                        // 更新用户信息
                        $updateImUser['Tag_Profile_Custom_jinyan'] = (string) Status::COMMON_RADIO_YES;
                        $resIm = (new Im()) -> updateUser($user['tx_code'], $updateImUser);
                        if (!$resIm) {
                            throw new Exception('更新用户信息失败');
                        }
                        $trans->commit();
                        return Functions::formatRestAPI(1,'!一分钟内向陌生人发送加好友申请十次的，自动作禁言处理');
                        // throw new Exception('!一分钟内向陌生人发送加好友申请十次的，自动作禁言处理');
                    }
                    $redis->setex('IM_APPLY_FRIEND_COUNT_'. $user['id'], 60, $applyCount + 1);
                }
            }else{
                $redis->setex('IM_APPLY_FRIEND_TIME_'. $user['id'], 60, time());
                $redis->setex('IM_APPLY_FRIEND_COUNT_'. $user['id'], 60, 1);
            }

            $exists = $redis->get(CacheKeys::IM_APPLY_FRIEND . $user['id'] . '_'. $searchUser['id']);
            if($exists){
                throw new Exception('您的速度太快了！');
            }
            $redis->set(CacheKeys::IM_APPLY_FRIEND . $user['id'] . '_'. $searchUser['id'], true);

            if ($type == Status::IM_ADD_FRIEND_TYPE_FANS) {
                # 自动同意
                (new Friend()) -> addFriend($user['id'],$searchUser['id']);
                $msg = "已自动添加对方为好友";
            } else {
                //是否是好友
                $isFriendWhere = $isFriendAndWhere = [];
//                $isFriendWhere['user_id'] = $user['id'];
//                $isFriendWhere['friend_id'] = $searchUser['id'];
                $isFriendAndWhere[] = [
                    'or',
                    [
                        'user_id' => $user['id'],
                        'friend_id' => $searchUser['id'],
                    ],
                    [
                        'user_id' => $searchUser['id'],
                        'friend_id' => $user['id'],
                    ],
                ];
                $isFriend = Friend::getOneByAndWhere($isFriendWhere,$isFriendAndWhere,'id');
                if (!empty($isFriend)) {
                    throw new Exception('已是好友，无需添加！');
                }

                if ($searchUser['id'] == $user['id']) {
                    throw new Exception('无法添加自己为好友！');
                }

                $applyData['user_id'] = $user['id'];
                $applyData['friend_id'] = $searchUser['id'];
                $check = static::getOneByWhere($applyData,'id');

                $applyData['status'] = Status::COMMON_CHECKING_WAITING;
                $applyData['message'] = $message;
                $applyData['create_time'] = date('Y-m-d H:i:s');
                if ($check) {
                    $applyData['type'] = $type;
                    $res = static::updateData($applyData,['id' => $check['id']]);
                } else {
                    $applyData['type'] = $type;
                    $applyData['user_phone'] = $user['login_name'];
                    $applyData['user_code'] = $user['user_code'];
//                $applyData['user_nick_name'] = $user['nick_name'];
//                $applyData['user_face'] = $user['user_face'];
                    $applyData['user_tx_code'] = $user['tx_code'];
                    $applyData['friend_phone'] = $searchUser['login_name'];
                    $applyData['friend_code'] = $searchUser['user_code'];
                    $applyData['friend_tx_code'] = $searchUser['tx_code'];
//                $applyData['friend_nick_name'] = $searchUser['nick_name'];
//                $applyData['friend_face'] = $searchUser['user_face'];
                    $res = static::insertData($applyData);
                }

                if ($res === false) {
                    throw new Exception('申请失败！');
                }
                $this->notReadApplyNum($searchUser['id']);
                $msg = "申请已发送";
            }

            $trans->commit();
            return Functions::formatRestAPI(0, $msg);
        } catch (\yii\db\Exception $ee) {
            return Functions::formatRestAPI(1, '服务异常');
        } catch (Exception $e) {
            $trans->rollBack();
            return Functions::formatRestAPI(1,$e->getMessage());
        } finally {
            $redis->del(CacheKeys::IM_APPLY_FRIEND . $user['id'] . '_'. $searchUser['id']);
        }
    }

    /**
     * 申请列表
     * @return array
     */
    public function getList()
    {
        try{
            $page = (int) Yii::$app->request->get('page',1);
            $size = (int) Yii::$app->request->get('size',20);
            $type = (int) Yii::$app->request->get('type',1); // 1-是我需要处理的好友申请 2-我自己申请的

            $user = (new User()) -> checkUser();

            $where = $andWhere = [];
            if ($type == 1) {
                $where['status'] = Status::COMMON_CHECKING_WAITING;
                $where['friend_id'] = $user['id'];
            }

            if ($type == 2) {
                $where['user_id'] = $user['id'];
            }


            $count = static::getCountByWhere($where);
            $data = static::setPageinationAPI($page, $size, $count);

            $offset = ($page - 1) * $size;
            $list = static::getObjectByWhere($where, ['*'], 'id DESC', $offset, $size)->with([
                'user' => function ($q) {
                    $q -> select(['id','nick_name','user_face']);
                },

                'friend' => function ($q) {
                    $q -> select(['id','nick_name','user_face']);
                },
            ])->asArray()->all();
            $result = [];
            foreach ($list as $v) {
                $singleUserInfo = ArrayHelper::getValue($v,'user',[]);
                $singleFriendInfo = ArrayHelper::getValue($v,'friend',[]);
                $tmp = [];
                if ($type == 1) {
                    $tmp = [
//                        'friend_id' => (int) $v['user_id'],
                        'friend_phone' => Functions::hiddenPhone($v['user_phone'], 3, 4),
                        'friend_tx_code' => $v['user_tx_code'],
                        'friend_nick_name' => $singleUserInfo['nick_name'] ?? '',
                        'friend_face' => static::getAvatar($singleUserInfo['user_face']),
                    ];
                }

                if ($type == 2) {
                    $tmp = [
//                        'friend_id' => (int) $v['friend_id'],
                        'friend_phone' => Functions::hiddenPhone($v['friend_phone'], 3, 4),
                        'friend_tx_code' => $v['friend_tx_code'],
                        'friend_nick_name' => $singleFriendInfo['nick_name'] ?? '',
                        'friend_face' => static::getAvatar($singleFriendInfo['user_face']),
                    ];
                }
                $tmp['message'] = $v['message'] ?: '';
                $tmp['status'] = (int) $v['status'];
                $tmp['create_time'] = $v['create_time'];
                $tmp['id'] = $v['id'];
                $result[] = $tmp;
            }
            $data['data'] = $result;
//            $this->notReadApplyNum($user['id']);
            return Functions::formatRestAPI(0, '', $data);
        } catch (\yii\db\Exception $ee) {
            return Functions::formatRestAPI(1, '服务异常');
        } catch(Exception $e){
            return Functions::formatRestAPI(1,$e->getMessage());
        }
    }

    /**
     * 处理好友申请
     * @return array
     */
    public function check() {
        $trans = static::getDb()->beginTransaction();

        try {
            $redis = Yii::$app->redis;
            $user = (new User()) -> checkUser();
            if (!$user || !$user['id']) {
                throw new Exception('未知用户信息！');
            }
            CacheKeys::checkFrequency("APPLY_FRIEND_CHECK".$user['id'],1);

            $id = (int) Yii::$app->request->post('id',0);
            $state = (int) Yii::$app->request->post('state',0);

            if (!$id) {
                throw new Exception('未知申请信息！');
            }

            if (!$state) {
                throw new Exception('审核状态有误！');
            }

            if (!in_array($state,[Status::COMMON_CHECKING_SUCCESS,Status::COMMON_CHECKING_DEFEAT])) {
                throw new Exception('审核状态有误！');
            }

            $info = static::getOneByWhere(['id' => $id]);
            if (empty($info)) {
                throw new Exception('申请信息不存在！');
            }

            if ($info['status'] != Status::COMMON_CHECKING_WAITING) {
                throw new Exception('申请信息已处理！');
            }

            if ($info['friend_id'] != $user['id']) {
                throw new Exception('非法请求！');
            }

            $friend = User::getObjectOneByWhere(['id' => $info['user_id']])->with()->asArray()->one();
            if (empty($friend) || !$friend['id']) {
                throw new Exception('好友信息不存在！');
            }

            $updateData['status'] = $state;
            $updateData['check_time'] = date('Y-m-d H:i:s');
            $res = static::updateData($updateData,['id' => $id]);
            if (empty($res)) {
                throw new Exception('好友申请处理失败！');
            }

            $imModel = (new Im());
            if ($state == Status::COMMON_CHECKING_SUCCESS) {
                //是否是好友
                $isFriendWhere = $isFriendAndWhere = [];
                $isFriendWhere['user_id'] = $user['id'];
                $isFriendWhere['friend_id'] = $friend['id'];
                $isFriend = Friend::getOneByWhere($isFriendWhere,'id');
                if (!empty($isFriend)) {
                    throw new Exception('已是好友，无需添加！');
                }

                if ($friend['id'] == $user['id']) {
                    throw new Exception('无法添加自己为好友！');
                }

                $friendOneData['user_id'] = $user['id'];
                $friendOneData['user_phone'] = $user['login_name'];
                $friendOneData['user_code'] = $user['user_code'];
                $friendOneData['user_tx_code'] = $user['tx_code'];
                $friendOneData['friend_id'] = $friend['id'];
                $friendOneData['friend_phone'] = $friend['login_name'];
                $friendOneData['friend_code'] = $friend['user_code'];
                $friendOneData['friend_tx_code'] = $friend['tx_code'];
                $friendOneData['create_time'] = date('Y-m-d H:i:s');
                $friendOneData['is_not_disturbing'] = Status::COMMON_RADIO_NO; //消息免打扰是否开启 1.是 2.否

                $friendOneData['type'] = $info['type'];

                $friendTwoData['friend_id'] = $user['id'];
                $friendTwoData['friend_phone'] = $user['login_name'];
                $friendTwoData['friend_code'] = $user['user_code'];
                $friendTwoData['friend_tx_code'] = $user['tx_code'];
                $friendTwoData['user_id'] = $friend['id'];
                $friendTwoData['user_phone'] = $friend['login_name'];
                $friendTwoData['user_code'] = $friend['user_code'];
                $friendTwoData['user_tx_code'] = $friend['tx_code'];
                $friendTwoData['create_time'] = date('Y-m-d H:i:s');
                $friendTwoData['is_not_disturbing'] = Status::COMMON_RADIO_NO; //消息免打扰是否开启 1.是 2.否

                $resOne = Friend::insertData($friendOneData);
                $resTwo = Friend::insertData($friendTwoData);

                if ($resOne === false || $resTwo === false) {
                    throw new Exception('好友添加失败！');
                }

                // IM
                $resIm = $imModel->addFriend($user['tx_code'],$friend['tx_code']);
                if (!$resIm) {
                    throw new Exception('好友添加失败');
                }

                // 修改好友信息
//                $updateImData['Tag_SNS_Custom_iscircle'] = (string) "1";
//                $resUpdateIm = $imModel->updateImFriend($user['tx_code'],$friend['tx_code'],$updateImData);
//                if (!$resUpdateIm) {
//                    throw new Exception('好友添加失败');
//                }
                (new Im()) -> sendSingleText($user['tx_code'],$friend['tx_code'],"我们已经是好友啦，一起来聊天吧！");

            }



            // 未读数量
            FriendApply::notReadApplyNum($user['id']);


            $trans->commit();
            return Functions::formatRestAPI(0, '处理成功');
        } catch (\yii\db\Exception $ee) {
            $trans->rollBack();
            return Functions::formatRestAPI(1, '服务异常');
        } catch (Exception $e) {
            $trans->rollBack();
            return Functions::formatRestAPI(1,$e->getMessage());
        }
    }


}
